package com.ysz.lock;

import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.KeeperException;

import java.util.List;
import java.util.Objects;

/**
 * @ClassName StandardLockInternalsDriver
 * @Description 操作zk的常规操作
 * @Data 14:04
 * @Version 1.0
 * @Author ysz
 */
public class StandardLockInternalsDriver implements LockInternalsDriver {

    @Override
    public String createsTheLock(CuratorFramework client, String path, byte[] lockNodeBytes) throws Exception {
        //使用容器节点保持一直监听
        //使用保护模式 在断开重连后可以一直重试
        String ourPath;
        if (Objects.nonNull(lockNodeBytes)) {
            ourPath = client.create().creatingParentContainersIfNeeded().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path, lockNodeBytes);
        } else {
            ourPath = client.create().creatingParentContainersIfNeeded().withProtection().withMode(CreateMode.EPHEMERAL_SEQUENTIAL).forPath(path);
        }
        return ourPath;
    }

    @Override
    public Result getsTheLock(CuratorFramework client, List<String> clildrens, String sequenceNodeName, int maxLeases) throws KeeperException.NoNodeException {
        //在所有的子锁节点中根据sequenceNodeName找到在集合中的下标，不存在抛异常
        int index = clildrens.indexOf(sequenceNodeName);
        if (index < 0) {
            throw new KeeperException.NoNodeException("Sequential path not found: " + sequenceNodeName);
        }
        //index为0则getTheLock为true
        //maxLeases是写死的值为1
        //目的是判断当前的sequenceNodeName是不是头节点
        boolean getTheLock = index < maxLeases;
        //拿到要监听的节点 即sequenceNodeName的上一个节点
        String pathToWatch = getTheLock ? null : clildrens.get(index - maxLeases);
        return new Result(getTheLock, pathToWatch);
    }


    @Override
    public String fixString(String completeWord, String lockName) {
        int index = completeWord.lastIndexOf(lockName);
        if (index >= 0) {
            index += lockName.length();
            return index >= completeWord.length() ? "" : completeWord.substring(index);
        }
        return completeWord;
    }
}
